package com.tianji.aigc.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.aigc.config.SessionProperties;
import com.tianji.aigc.domain.po.ChatSession;
import com.tianji.aigc.domain.vo.ChatSessionVO;
import com.tianji.aigc.domain.vo.MessageVO;
import com.tianji.aigc.domain.vo.SessionVO;
import com.tianji.aigc.mapper.ChatSessionMapper;
import com.tianji.aigc.memory.MyAssistantMessage;
import com.tianji.aigc.service.IChatSessionService;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.UserContext;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.springframework.ai.chat.messages.MessageType.ASSISTANT;
import static org.springframework.ai.chat.messages.MessageType.USER;

/**
 * <p>
 * 对话session 服务实现类
 * </p>
 *
 * @author 东哥
 * @since 2025-07-21
 */
@Service
@RequiredArgsConstructor
public class ChatSessionServiceImpl extends ServiceImpl<ChatSessionMapper, ChatSession> implements IChatSessionService {
    private final SessionProperties sessionProperties;
    private final ChatMemory chatMemory;

    /**
     * 1- 新建会话(Day1 - 随堂1)
     *
     * @param num 热门问题数量
     */
    @Override
    public SessionVO createSession(Integer num) {
        // 1、组装vo数据
        // 1.1、拷贝 sessionPropertis数据至 sessionVo
        SessionVO sessionVO = BeanUtils.toBean(sessionProperties, SessionVO.class);

        // 1.2、随机生成num数量的热门问题
        sessionVO.setExamples(RandomUtil.randomEleList(sessionVO.getExamples(), num));

        // 1.2、生成sessionId
        sessionVO.setSessionId(IdUtil.fastSimpleUUID());

        // 2、组装会话session数据，存入数据库
        ChatSession chatSession = ChatSession.builder()
                .sessionId(sessionVO.getSessionId())
                .userId(UserContext.getUser())
                .build();
        this.save(chatSession);
        return sessionVO;
    }

    /**
     * 2- 换一换-热门问题(Day1 - 随堂2)
     *
     * @param num
     */
    @Override
    public List<SessionVO.Example> hot(Integer num) {
        return RandomUtil.randomEleList(sessionProperties.getExamples(), num);
    }

    /**
     * 3、通过 会话ID 获取会话详情(Day1 - 作业2)
     *
     * @param sessionId
     * @return
     */
    @Override
    public List<MessageVO> getChatRecord(String sessionId) {
        List<Message> messages = chatMemory.get(sessionId, Integer.MAX_VALUE);
        return messages.stream()
                .filter(message -> message.getMessageType() == USER || message.getMessageType() == ASSISTANT)
                .map(message -> {
                    // 解决根据会话ID查询历史会话记录，课程卡片json反显问题
                    if(message instanceof MyAssistantMessage){
                        return new MessageVO(message.getMessageType(), message.getText(), ((MyAssistantMessage) message).getParams());
                    }
                    return new MessageVO(message.getMessageType(), message.getText());
                })
                .collect(Collectors.toList());
    }

    /**
     * 4、异步更新会话标题(Day3 - 随堂1)
     * @param sessionId
     * @param userId
     * @param title
     */
    @Async
    @Override
    public void update(String sessionId,Long userId,String title){
        // 1、查询符合条件的聊天会话列表
        ChatSession chatSession = this.lambdaQuery()
                .eq(ChatSession::getSessionId, sessionId)
                .eq(ChatSession::getUserId, userId)
                .one();
        // 2、如果会话为空，直接返回，无需进一步处理
        if (ObjectUtil.isEmpty(chatSession)) {
            return;
        }

        // 3、如果原来会话的标题为空 且 新标题不为空，则更新标题
        if (ObjectUtil.isEmpty(chatSession.getTitle()) && ObjectUtil.isNotEmpty(title)) {
            chatSession.setTitle(StrUtil.sub(title, 0, 100));  // 最多100个字符
        }

        // 每次都要修改 更新时间，将来历史会话记录需要按 这个时间进行排序
        chatSession.setUpdateTime(LocalDateTimeUtil.now());
        // 4、更新数据库中的聊天会话信息
        this.updateById(chatSession);
    }

    /**
     * 5、查询历史会话列表 - Day3 - 随堂2
     *
     * @return
     */
    @Override
    public Map<String, List<ChatSessionVO>> queryHistorySession() {
        // 1、查询历史会话列表
        // select * from chat_session where user_id = ? and title is not null order by update_time desc limit 30
        List<ChatSession> sessionHisList = this.lambdaQuery()
                .eq(ChatSession::getUserId, UserContext.getUser())
                .isNotNull(ChatSession::getTitle)
                .orderByDesc(ChatSession::getUpdateTime)
                .last("limit 30")
                .list();
        if (ObjectUtil.isEmpty(sessionHisList)) {
            return Map.of();
        }

        // 2、将po list 转为 vo list
        List<ChatSessionVO> sessionVoList = CollStreamUtil.toList(sessionHisList, chatSession -> BeanUtils.toBean(chatSession, ChatSessionVO.class));

        // 3、对voList进行分组
        LocalDateTime now = LocalDateTime.now();
        /*sessionVoList.stream().collect(Collectors.groupingBy(session -> {
            long between = LocalDateTimeUtil.between(now, session.getUpdateTime(), ChronoUnit.DAYS);
            if (between == 0) {
                return "当天";
            } else if (between <= 30) {
                return "最近30天";
            } else if (between <= 365) {
                return "最近1年";
            } else {
                return "1年以上";
            }
        }));*/

        // 4、返回
        return CollStreamUtil.groupByKey(sessionVoList,session -> {
            long between = Math.abs(LocalDateTimeUtil.between(now, session.getUpdateTime(), ChronoUnit.DAYS));
            if (between == 0) {
                return "当天";
            } else if (between <= 30) {
                return "最近30天";
            } else if (between <= 365) {
                return "最近1年";
            } else {
                return "1年以上";
            }
        });
    }

    /*public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime end = LocalDateTime.of(2024, 6, 24, 10, 25, 32);
        long between = Math.abs(LocalDateTimeUtil.between(now, end, ChronoUnit.DAYS));
        System.out.println("between = " + between);
    }*/

    /**
     * 6、删除历史会话列表- Day3 - 练习1
     *
     * @param sessionId 会话id
     */
    @Override
    public void deleteHistorySession(String sessionId) {
        // 1、删除数据库的数据
        LambdaQueryWrapper<ChatSession> queryWrapper = Wrappers.<ChatSession>lambdaQuery()
                .eq(ChatSession::getSessionId, sessionId)
                .eq(ChatSession::getUserId, UserContext.getUser());
        super.remove(queryWrapper);

        // 2、删除redis中的数据
        this.chatMemory.clear(sessionId);
    }

    /**
     * 7、更新历史会话标题- Day3 - 练习2
     *
     * @param sessionId 会话id
     * @param title     标题
     */
    @Override
    public void updateTitle(String sessionId, String title) {
        //更新数据
        this.lambdaUpdate()
                // 设置更新条件, 更新字段为title(最多设置前100个字符)，更新条件为sessionId 和 userId
                .set(ChatSession::getTitle, StrUtil.sub(title, 0, 100))
                .eq(ChatSession::getSessionId, sessionId)
                .eq(ChatSession::getUserId, UserContext.getUser())
                .update();
    }
}
